home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cmidilib.zip
/
MIDIFILE.DOC
< prev
next >
Wrap
Text File
|
1991-08-23
|
14KB
|
463 lines
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
NAME
mfread,mfwrite - read and write a standard MIDI file
SYNOPSIS
#include "mfread.h"
mfread ()
int (*Mf_getc) ();
int (*Mf_putc) ();
int (*Mf_error) (char *msg);
int (*Mf_header) (int format, int ntrks, int division);
int (*Mf_trackstart) ();
int (*Mf_trackend) ();
int (*Mf_noteon) (int chan, int pitch, int vol);
int (*Mf_noteoff) (int chan, int pitch, int vol);
int (*Mf_pressure) (int chan, int pitch, int pressure);
int (*Mf_parameter) (int chan, int control, int value);
int (*Mf_pitchbend) (int chan, int msb, int lsb);
int (*Mf_program) (int chan, int program);
int (*Mf_chanpressure) (int chan, int pressure);
int (*Mf_sysex) (int leng, char *msg);
int (*Mf_metamisc) (int type, int leng, int msg);
int (*Mf_seqspecific) (int type, int leng, int msg);
int (*Mf_seqnum) (int num);
int (*Mf_text) (int type, int leng, int msg);
int (*Mf_eot) ();
int (*Mf_timesig) (int numer, int denom, int clocks, int qnotes);
int (*Mf_smpte) (int hour, int min, int sec, int frame, int fract);
int (*Mf_tempo) (int microsecs);
int (*Mf_keysig) (int sharpflat, int minor);
int (*Mf_arbitrary) (int leng, int msg);
int Mf_nomerge;
long Mf_currtime;
mfwrite(int format, int ntracks, int division, FILE *fp)
int (*Mf_writetrack)(int track);
int (*Mf_writetempotrack)();
void mf_write_midi_event(delta, type, chan, data, size)
unsigned long delta;
unsigned int type,chan,size;
char *data;
void mf_write_meta_event(delta, type, data, size)
unsigned long delta;
unsigned int type,chan,size;
char *data;
void mf_write_tempo(tempo)
unsigned long tempo;
Sun Release 4.1 Last change: 1
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
unsigned long mf_sec2ticks(float seconds, int division, int tempo)
float seconds;
int division;
unsigned int tempo;
float mf_ticks2sec(ticks, division, tempo)
unsigned long ticks;
int division;
unsigned int tempo;
DESCRIPTION
The mfread function reads and inteprets a standard MIDI
file. To use it you need to understand the general form of
a MIDI file and the type of information it contains, but you
don't need to know much, if anything, about the detailed
format of the file and the mechanics of reading it reliably
and portably.
The mfwrite function writes a standard MIDI file making use
of user-defined functions that access the program's data
structure. To use it you need to define your own
Mf_writetrack routine and then make use of the write_* fam-
ily of routines to write out the MIDI data. The mfwrite
routine takes care of the file format and writing the file
and track chunk headers.
READING STANDARD MIDI FILES
A single call to mfread will read an entire MIDI file. The
interface to mfread is a set of external variables named
Mf_*, most of which are function pointers to be called from
within mfread during the process of parsing the MIDI file.
Before calling mfread, the only requirement is that you
assign a value to Mf_getc - a pointer to a function that
will return characters from the MIDI file, using -1 to indi-
cate EOF. All the rest of the function pointers are ini-
tialized to NULL, and the default action for each is to do
nothing. The following is a complete program using mfread
that could serve as a 'syntax checker' for MIDI files:
#include <stdio.h>
#include "midifile.h"
mygetc()
{
/* use standard input */
return(getchar());
}
main()
{
Sun Release 4.1 Last change: 2
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
Mf_getc = mygetc;
mfread();
exit(0);
}
This takes advantage of the default action when an error is
detected, which is to exit silently with a return code of 1.
An error function of your own can be used by giving a value
to Mf_error; the function will be called with the error mes-
sage as an argument. The other Mf_* variables can similarly
be used to call arbitrary functions while parsing the MIDI
file. The descriptions below of the information passed to
these functions is sparse; refer to the MIDI file standard
for the complete descriptions.
Mf_header is the first function to be called, and its argu-
ments contain information from the MIDI file's header; the
format (0,1, or 2), the number of tracks, and the division
of a quarter-note that defines the times units.
Mf_trackstart and Mf_trackend are called at the beginning
and end of each track.
Once inside a track, each separate message causes a function
to be called. For example, each note-on message causes
Mf_noteon to be called with the channel, pitch, and volume
as arguments. The time at which the message occurred is
stored in Mf_currtime - one of the few external variables
that isn't a function pointer. The other channel messages
are handled in a similar and obvious fashion - Mf_noteoff,
Mf_pressure, Mf_parameter, Mf_pitchbend, Mf_program, and
Mf_chanpressure. See the declarations above for the argu-
ments that are passed to each.
System exclusive messages are handled by calling Mf_sysex,
passing as arguments the message length and a pointer to a
static buffer containing the entire message. The buffer is
expanded when necessary; memory availability is the only
limit to its size. Normally, 'continued' system exclusives
are automatically merged, and Mf_sysex is only called once.
It you want to disable this you can set Mf_nomerge to 1,
causing Mf_sysex to be called once for each part of the mes-
sage.
Mf_seqnum is called by the meta message that provides a
sequence number, which if present must appear at the begin-
ning of a track. The tempo meta message causes Mf_tempo to
be called; its argument is the number of microseconds per
MIDI quarter-note (24 MIDI clocks). The end-of-track meta
message causes Mf_eot to be called. The key signature meta
message causes Mf_keysig to be called; the first argument
conveys the number of sharps or flats, the second argument
is 1 if the key is minor.
Sun Release 4.1 Last change: 3
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
The Mf_timesig and Mf_smpte functions are called when the
corresponding meta messages are seen. See the MIDI file
standard for a description of their arguments.
The text messages in the MIDI file standard are of the fol-
lowing types:
0x01 Text Event
0x02 Copyright
0x03 Sequence/Track Name
0x04 Instrument
0x05 Lyric
0x06 Marker
0x07 Cue Point
0x08-0x0F Reserverd but Undefined
Mf_text is called for each of these; the arguments are the
type number, the message length, and a pointer to the mes-
sage buffer.
Misceallaneous meta messages are handled by Mf_metamisc,
sequencer-specific messages are handled by Mf_seqspecific,
and arbitrary "escape" messages (started with 0xF7) are han-
dled by Mf_arbitrary.
READING EXAMPLE
The following is a strings-like program for MIDI files:
#include <stdio.h>
#include <ctype.h>
#include "midifile.h"
FILE *F;
mygetc() { return(getc(F)); }
mytext(type,leng,msg)
char *msg;
{
char *p;
char *ep = msg + leng;
for ( p=msg; p<ep ; p++ )
putchar( isprint(*p) ? *p : '?' );
putchar('0);
}
main(argc,argv)
char **argv;
{
if ( argc > 1 )
F = fopen(argv[1],"r");
Sun Release 4.1 Last change: 4
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
else
F = stdin;
Mf_getc = mygetc;
Mf_text = mytext;
mfread();
exit(0);
}
WRITING STANDARD MIDI FILES
A single call to mfwrite will write an entire MIDI file.
Before calling mfwrite, you must assign values to function
pointers Mf_writetrack and Mf_putc. The first is a routine
to access your MIDI data structure, which can make use of
other library routines to write the actual MIDI data. The
routine Mf_writetrack will be passed a single parameter
which is the number of the track to be written. The pointer
Mf_putc should be set to point to a routine that accepts a
charcter as input, writes that character to a file, and
returns the value that was written. In the case of a format
1 file, a routine has to be written to write a tempo map,
and assigned to the function pointer Mf_writetempotrack.
This is because format 1 files assume the first track writ-
ten is a tempo track.
mf_write_midi_event and mf_write_meta_event are routines
that should be called from your Mf_writetrack routine to
write out MIDI events. The delta time param is the number
of ticks since the last event. The int "type" is the type
of MIDI message. The int "chan" is the MIDI channel, which
can be between 1 and 16. The char pointer "data" points to
an array containing the data bytes, if any exist. The int
"size" is the number of data bytes.
mf_sec2ticks and mf_ticks2sec are utility routines to help
you convert between the MIDI file parameter of ticks and the
more standard seconds. The int "division" is the same divi-
sion parameter from the file header, and tempo is expressed
in microseconds per MIDI quarter-note, or "24ths of a
microsecond per MIDI clock". The division has two meanings,
depending on whether bit 15 is set or not. If bit 15 of
division is zero, bits 14 through 0 represent the number of
delta-time "ticks" which make up a quarter note. If bit 15
of division is a one, delta-times in a file correspond to
subdivisions of a second similiar to SMPTE and MIDI time
code. In this format bits 14 through 8 contain one of four
values - 24, -25, -29, or -30, corresponding to the four
standard SMPTE and MIDI time code frame per second formats,
where -29 represents 30 drop frame. The second byte
Sun Release 4.1 Last change: 5
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
consisting of bits 7 through 0 corresponds the the resolu-
tion within a frame. Refer the Standard MIDI Files 1.0 spec
for more details.
WRITING EXAMPLE
The following is a simple program to demonstrate writing
MIDI files. The track would consist of a series of quarter
notes from lowest to highest in pitch at constant velocity,
each separted by a quarter-note rest.
#include <stdio.h>
#include <ctype.h>
#include "midifile.h"
FILE *fp;
myputc(c) { return(putc(c,fp));}
int mywritetrack(track)
int track;
{
int i;
char data[2];
/* 120 beats/per/second */
mf_write_tempo((long)500000);
for(i = 1 ; i < 128; i++){
data[0] = i; /* note number */
data[1] = 64; /* velocity */
if(!mf_write_midi_event(480,note_on,1,data,2))
return(-1);
if(!mf_write_midi_event(480,note_off,1,data,2))
return(-1);
}
return(1);
} /* end of write_track() */
main(argc,argv)
char **argv;
{
if((fp = fopen(argv[1],"w")) == 0L)
exit(1);
Mf_putc = myputc;
Mf_writetrack = mywritetrack;
/* write a single track */
mfwrite(0,1,480,fp);
}
Sun Release 4.1 Last change: 6
MIDIFILE(3) C LIBRARY FUNCTIONS MIDIFILE(3)
AUTHOR
Tim Thompson (att!twitch!glimmer!tjt)
CONTRIBUTORS
Michael Czeiszperger (mike@pan.com)
Sun Release 4.1 Last change: 7